from threading import Timer
import curses

from .frame import draw_frame


class PeriodicTimer():
    def __init__(self, fn, period):
        def bound():
            fn()
            self.windup()

        self.fn = bound
        self.period = period
        self.windup()

    def windup(self):
        self.timer = Timer(self.period, self.fn)
        self.timer.start()

    def cancel(self):
        if self.timer is not None:
            self.timer.cancel()


class Sermon:
    REFRESH_TIMEOUT = 0.3
    UPDATE_TIMEOUT = 3

    def __init__(self, scr, services):
        self.scr = scr
        self.quit = False
        self.frame_timer = None
        self.update_timers = []
        self.services = services

    def run(self):
        self.update_timers = list(map(
            lambda service: PeriodicTimer(
                service.update,
                Sermon.UPDATE_TIMEOUT),
            self.services))

        self.frame_timer = PeriodicTimer(self.frame, Sermon.REFRESH_TIMEOUT)

        curses.curs_set(0)
        curses.use_default_colors()

        while not self.quit:
            self.frame()
            key = self.scr.getkey()
            self.input(key)

        self.frame_timer.cancel()

        for timer in self.update_timers:
            timer.cancel()

    def frame(self):
        self.scr.erase()
        draw_frame(self.scr, self.services)
        self.scr.refresh()

    def input(self, key):
        if key == 'q':
            self.quit = True
        else:
            triggered_service = next(iter(filter(lambda srv: srv.tag == key,
                                                 self.services)),
                                     None)

            if triggered_service is not None:
                triggered_service.toggle()
